using System.Collections.Generic;
using UnityEngine;


namespace GridSystem
{
    public class PlaceController : MonoBehaviour
    {
        // 放置模式枚举
        public enum PlacementMode
        {
            网格吸附模式,
            自由摆放模式
        }

        // 内部状态机
        private enum PlacingState
        {
            待机,
            拖拽中
        }

        [Header("配置")]
        [Tooltip("当前网格层")]
        public List<GridSurface> gridSurfaces = new List<GridSurface>();

        [Tooltip("当前放置模式")]
        public PlacementMode currentMode = PlacementMode.网格吸附模式;

        [Tooltip("可以被射线检测到的可放置物体层")]
        public LayerMask placeableObjectLayer;

        [Tooltip("可以被射线检测到的网格表面层")]
        public LayerMask gridSurfaceLayer;

        [Tooltip("网格吸附模式下每次旋转的角度")]
        public float gridRotationAngle = 90f;

        [Tooltip("自由摆放模式下每秒的旋转速度")]
        public float freeRotationSpeed = 180f;

        // 状态变量
        private PlacingState _currentState = PlacingState.待机;
        private Camera _mainCamera;

        // 拖拽相关
        private PlaceableObject _selectedObject; // 原始被选中的对象
        private Transform _ghostObject; // 用于预览的“幽灵”对象
        private Vector3 _dragOffset; // 鼠标点击位置与物体中心的偏移
        private float _dragPlaneDistance; // 拖拽平面的距离

        // 旋转相关
        private float _currentYRotation = 0f;

        // 预览相关
        private GridSurface _currentSurface;
        private bool _canPlace;
        private List<Vector2Int> _currentFootprint = new();

        private void Start()
        {
            _mainCamera = Camera.main;
        }

        private void Update()
        {
            switch (_currentState)
            {
                case PlacingState.待机:
                    HandleSelection();
                    break;
                case PlacingState.拖拽中:
                    HandleDrag(); // 1. 优先处理位置和父级关系
                    HandleRotation(); // 2. 处理旋转输入，更新旋转值
                    ApplyGhostTransform(); // 3. 最后统一应用位置和旋转
                    UpdateFootprintPreview(); // 4. 更新可视化
                    HandlePlacementConfirmation();
                    HandleCancellation();
                    break;
            }
        }

        #region State: Idle
        private void HandleSelection()
        {
            if (Input.GetMouseButtonDown(0))
            {
                Ray ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
                if (Physics.Raycast(ray, out RaycastHit hit, 1000f, placeableObjectLayer))
                {
                    if (hit.collider.TryGetComponent<PlaceableObject>(out var placeable))
                    {
                        StartPlacing(placeable);
                    }
                }
            }
        }
        #endregion

        #region State: Dragging

        private void HandleDrag()
        {
            Ray ray = _mainCamera.ScreenPointToRay(Input.mousePosition);

            Debug.DrawLine(ray.origin, ray.direction * 1000f, Color.red);

            // 优先检测GridSurface
            if (Physics.Raycast(ray, out RaycastHit surfaceHit, 1000f, gridSurfaceLayer))
            {
                if (surfaceHit.collider.TryGetComponent<GridSurface>(out var detectedSurface))
                {
                    // 如果切换到了新的表面
                    if (_currentSurface != detectedSurface)
                    {
                        _currentSurface = detectedSurface;
                        _ghostObject.SetParent(_currentSurface.transform);
                        //_ghostObject.localScale = Vector3.one;
                    }
                    UpdateGhostPositionOnSurface(surfaceHit.point);
                }
            }
            else // 如果没检测到GridSurface，则在相机平面上移动
            {
                // 如果离开了所有表面
                if (_currentSurface != null)
                {
                    _currentSurface = null;
                    // 保存当前世界变换信息，然后脱离父级
                    Vector3 worldPos = _ghostObject.position;
                    Quaternion worldRot = _ghostObject.rotation;
                    Vector3 worldScale = _ghostObject.lossyScale;
                    _ghostObject.SetParent(null);
                    // 重新应用，防止SetParent(null)时的意外变换
                    _ghostObject.position = worldPos;
                    _ghostObject.rotation = worldRot;
                    _ghostObject.localScale = worldScale;
                }
                UpdateGhostPositionOnCameraPlane(ray);
            }

            UpdateFootprintPreview();
        }

        private void HandleRotation()
        {
            float rotationInput = 0;
            if (Input.GetKey(KeyCode.E)) rotationInput = 1;
            if (Input.GetKey(KeyCode.Q)) rotationInput = -1;

            if (rotationInput != 0)
            {
                if (currentMode == PlacementMode.网格吸附模式)
                {
                    // 按键按下时旋转固定角度
                    if (Input.GetKeyDown(KeyCode.E) || Input.GetKeyDown(KeyCode.Q))
                    {
                        _currentYRotation += rotationInput * gridRotationAngle;
                    }
                }
                else // Free Mode
                {
                    _currentYRotation += rotationInput * freeRotationSpeed * Time.deltaTime;
                }
            }
        }

        private void HandlePlacementConfirmation()
        {
            if (Input.GetMouseButtonUp(0))
            {
                if (_canPlace && _currentSurface != null && _selectedObject != null)
                {
                    PlaceObject();
                }
                else
                {
                    CancelPlacing();
                }
            }
        }

        private void HandleCancellation()
        {
            if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape))
            {
                CancelPlacing();
            }
        }

        #endregion

        #region Core Logic
        private void StartPlacing(PlaceableObject obj)
        {
            _selectedObject = obj;
            _currentState = PlacingState.拖拽中;

            // 如果物体已在某个表面上，先将其移除
            if (obj.OccupiedSurface != null)
            {
                obj.OccupiedSurface.FreeCells(obj.OccupiedCells);
                obj.OccupiedSurface = null;
                obj.OccupiedCells = null;
            }

            // 在拾取时，将物体从任何父级中脱离
            _selectedObject.transform.SetParent(null);
            // 创建幽灵预览
            _ghostObject = Instantiate(_selectedObject.gameObject).transform;
            // 移除预览物体上的 PlaceableObject 和 Collider，避免干扰
            Destroy(_ghostObject.GetComponent<PlaceableObject>());
            if (_ghostObject.TryGetComponent<Collider>(out var col)) Destroy(col);

            // 隐藏原始物体
            _selectedObject.gameObject.SetActive(false);

            _currentYRotation = _ghostObject.eulerAngles.y;

            // 计算拖拽偏移
            _dragPlaneDistance = Vector3.Dot(_ghostObject.position - _mainCamera.transform.position, _mainCamera.transform.forward);
            _dragOffset = _ghostObject.position - _mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, _dragPlaneDistance));
        }

        private void UpdateGhostPositionOnSurface(Vector3 surfaceHitPoint)
        {
            // 计算最终的局部Y偏移 = 表面偏移 - 物体自身偏移
            float combinedYOffset = _currentSurface.yOffset - _selectedObject.yOffset;

            if (currentMode == PlacementMode.网格吸附模式)
            {
                // 吸附到网格中心
                Vector2Int localPos = _currentSurface.WorldToLocal(surfaceHitPoint);
                _ghostObject.localPosition = new Vector3(localPos.x * _currentSurface.cellSize, combinedYOffset, localPos.y * _currentSurface.cellSize);
            }
            else // Free Mode
            {
                Vector3 localHitPoint = _currentSurface.transform.InverseTransformPoint(surfaceHitPoint);
                // 自由模式下，Y值被固定为组合偏移，确保物体始终贴在正确的逻辑高度上
                _ghostObject.localPosition = new Vector3(localHitPoint.x, combinedYOffset, localHitPoint.z);
            }
        }

        private void UpdateGhostPositionOnCameraPlane(Ray ray)
        {
            // 在与相机平行的平面上移动
            var plane = new Plane(-_mainCamera.transform.forward, _ghostObject.position);
            if (plane.Raycast(ray, out float distance))
            {
                _ghostObject.position = ray.GetPoint(distance) + _dragOffset;
            }
        }

        private void ApplyGhostTransform()
        {
            // 统一在这里应用旋转，确保无论在哪都能响应旋转输入
            if (_currentSurface != null)
            {
                // 在表面上时，应用局部旋转（绕表面法线）
                _ghostObject.localRotation = Quaternion.Euler(0, _currentYRotation, 0);
            }
            else
            {
                // 在空中时，应用世界旋转（绕世界Y轴）
                _ghostObject.rotation = Quaternion.Euler(_ghostObject.rotation.eulerAngles.x, _currentYRotation, _ghostObject.rotation.eulerAngles.z);
            }
        }

        private void UpdateFootprintPreview()
        {
            if (_ghostObject == null || _currentSurface == null)
            {
                _canPlace = false;
                _currentFootprint.Clear();
            }
            else
            {
                if (_selectedObject.cellSize != _currentSurface.cellSize)
                {
                    _canPlace = false;
                    _currentFootprint.Clear();
                }
                else
                {
                    _currentFootprint = _selectedObject.CalculateWorldCells(_currentSurface, _ghostObject.position, _ghostObject.rotation);
                    _canPlace = _currentSurface.CheckPlacementValidity(_currentFootprint);
                }
            }

            // 【需求 #6】 调用可视化系统API来更新预览
#if UNITY_EDITOR
            // 【修改】通过事件系统触发预览更新，而不是直接调用
            GridSystemEvents.RaisePlacementPreview(_currentSurface, _currentFootprint, _canPlace, _selectedObject);
#endif
        }

        private void PlaceObject()
        {
            // 最终放置时，将原始物体设置为GridSurface的子物体
            _selectedObject.transform.SetParent(_currentSurface.transform);
            _selectedObject.transform.position = _ghostObject.position;
            _selectedObject.transform.rotation = _ghostObject.rotation;

            _currentSurface.OccupyCells(_currentFootprint, _selectedObject);
            _selectedObject.OccupiedSurface = _currentSurface;
            _selectedObject.OccupiedCells = _currentFootprint;

            EndPlacing();
        }

        private void CancelPlacing()
        {
            EndPlacing();
        }

        private void EndPlacing()
        {
            // 如果没有成功放置，物体应该返回到它被拾取前的位置状态，
            // 但为了简化，我们暂时只让它在原地显示。可以后续增加返回逻辑。
            _selectedObject.gameObject.SetActive(true);

            if (_ghostObject != null) Destroy(_ghostObject.gameObject);

#if UNITY_EDITOR
            // 通过事件系统触发清除预览
            GridSystemEvents.RaiseClearPlacementPreview();
#endif


            _currentState = PlacingState.待机;
            _selectedObject = null;
            _currentSurface = null;
            _currentFootprint.Clear();
        }

        #endregion
    }
}